package com.vanzo.talkie;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.widget.TextView;

import com.vanzo.talkie2.R;
import com.vanzo.util.LogUtil;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidParameterException;
import java.security.PublicKey;

import android_serialport_api.SerialPort;

/**
 * Created by tisen on 2018/1/9.
 */

public class ATHelper {


    private static final String DEVICE_PATH = "/dev/ttyMT0";
    private static final int DEVICE_BAUD_RATE = 9600;

//    private Context context;

    protected com.vanzo.talkie.Application mApplication;
    protected SerialPort mSerialPort;
    protected OutputStream mOutputStream;
    private InputStream mInputStream;
    private ReadThread mReadThread;

    private Callback callback;
    private logCall logCall;

    public void setLogCall(ATHelper.logCall logCall) {
        this.logCall = logCall;
    }

    public interface Callback {
        void callback(String result);
    }

    private static ATHelper atHelper;

    public static ATHelper getInstance(Application application) {
        if (atHelper == null) {
            atHelper = new ATHelper();
            atHelper.init(application, DEVICE_PATH, DEVICE_BAUD_RATE);
        }
        return atHelper;
    }


    private SqStatusCallback sqCallback;
    private PowerStatusCallback powerStatusCallback;

    public interface PowerStatusCallback {
        void ok(String result);

        void fail(String result);
    }

    public interface SqStatusCallback {
        void open(String result);

        void close(String result);
    }


    public void setSqStatusCallback(SqStatusCallback sqCallback) {
        this.sqCallback = sqCallback;
    }

    public void setPowerStatusCallback(PowerStatusCallback powerStatusCallback) {
        this.powerStatusCallback = powerStatusCallback;
    }

    private class ReadThread extends Thread {

        @Override
        public void run() {
            super.run();
            while (!isInterrupted()) {
                int size = 0;
                try {
                    byte[] buffer = new byte[128];
                    if (mInputStream == null) return;
                    size = mInputStream.read(buffer);
                    if (size > 0) {
                        onDataReceived(buffer, size);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    LogUtil.put("ATHelper", "size = " + size, e);
                    return;
                }
            }
        }
    }

    private static final String SQ_STATUS_CLOSE = "+DMOGETSQSTATUS:0";
    private static final String SQ_STATUS = "+DMOGETSQSTATUS";
    private static final String SQ_STATUS_OPEN = "+DMOGETSQSTATUS:1";

    private static final String POWER_STATUS_FAIL = "+DMOGETSTARTUP:1";
    private static final String POWER_STATUS = "+DMOGETSTARTUP";
    private static final String POWER_STATUS_OK = "+DMOGETSTARTUP:0";


    private static final String patternString = "\\r\\n+DMO\\r\\n";

    private void onDataReceived(final byte[] buffer, int size) {
//        LogUtil.put(this, "size = " + size, LogUtil.WARN);
        temp.append(new String(buffer, 0, size));
        LogUtil.put(this, "onDataReceived = " + temp.toString(), LogUtil.WARN);
        if (temp.toString().endsWith("\r\n")) {
            LogUtil.put(this, "on AT received = " + temp.toString(), LogUtil.WARN);
            if (logCall != null) {
                logCall.onLogPut("\r\n返回的指令 = " + temp.toString().trim());
            }
            if (temp.toString().contains(SQ_STATUS_CLOSE) && sqCallback != null) {
                sqCallback.close(temp.toString());
            } else if (temp.toString().contains(SQ_STATUS_OPEN) && sqCallback != null) {
                sqCallback.open(temp.toString());
            } else if (temp.toString().contains(POWER_STATUS_FAIL) && powerStatusCallback != null) {
                powerStatusCallback.fail(temp.toString());
            } else if (temp.toString().contains(POWER_STATUS_OK) && powerStatusCallback != null) {
                powerStatusCallback.ok(temp.toString());
            } else if (callback != null) {
                callback.callback(temp.toString());
                callback = null;
            }
            temp = new StringBuilder();
        } else {

        }
    }

    private StringBuilder temp = new StringBuilder();

    public ATHelper(com.vanzo.talkie.Application application, String devicePath, int baudrate) {
        init(application, devicePath, baudrate);
    }

    public ATHelper(Application application) {
        init(application, DEVICE_PATH, DEVICE_BAUD_RATE);
    }

    public ATHelper() {
    }

    public void init(Application application, String devicePath, int baudrate) {
        mApplication = application;
        try {
            mSerialPort = mApplication.getSerialPort(devicePath, baudrate);
            mOutputStream = mSerialPort.getOutputStream();
            mInputStream = mSerialPort.getInputStream();

			/* Create a receiving thread */
        } catch (SecurityException e) {
            DisplayError(R.string.error_security);
        } catch (IOException e) {
            DisplayError(R.string.error_unknown);
        } catch (InvalidParameterException e) {
            DisplayError(R.string.error_configuration);
        }
    }

    private void DisplayError(int resourceId) {
//        AlertDialog.Builder b = new AlertDialog.Builder(context);
//        b.setTitle("Error");
//        b.setMessage(resourceId);
//        b.setPositiveButton("OK", new DialogInterface.OnClickListener() {
//            public void onClick(DialogInterface dialog, int which) {
//
//            }
//        });
//        b.show();
    }


    /*

    设置频道信息
     */


    private static String AT_DMOSETGROUP = "AT+DMOSETGROUP";

    public void setChannel(boolean mode, boolean gbw, boolean power, String tfv, String rfv, String txcxcss, String rxcxcss, String sq, Callback callback) {
        String atCmd = AT_DMOSETGROUP + "=" + (!mode ? 1 : 2)
                + "," + (!gbw ? 0 : 1)
                + "," + tfv
                + "," + rfv
                + "," + txcxcss
                + "," + rxcxcss
                + "," + sq
                + "," + (!power ? 0 : 1);
        sendATCmd(atCmd, callback);
    }

    /*
    设置mic增益
     */


    private static String AT_DMOSETMIC = "AT+DMOSETMIC";

    public void setMic(String mode, Callback callback) {
        String atCmd = AT_DMOSETMIC + "=" + mode;
        sendATCmd(atCmd, callback);
    }


    /*
    设置音量
     */

    private static String AT_DMOSETVOLUME = "AT+DMOSETVOLUME";

    public void setVolume(String volume, Callback callback) {
        String atCmd = AT_DMOSETVOLUME + "=" + volume;
        sendATCmd(atCmd, callback);
    }

    private static String AT_DMOSETVOX = "AT+DMOSETVOX";

    public void setVox(int vox, Callback callback) {
        String atCmd = AT_DMOSETVOX + "=" + vox;
        sendATCmd(atCmd, callback);
    }

    private static String AT_DMOSETAPC = "AT+DMOSETAPC";

    public void setApc(int apc, Callback callback) {
        String atCmd = AT_DMOSETAPC + "=" + apc;
        sendATCmd(atCmd, callback);
    }

    private static String AT_DMOPTT = "AT+DMOPTT";

    public void setPtt(int ptt, Callback callback) {
        String atCmd = AT_DMOPTT + "=" + ptt;
        sendATCmd(atCmd, callback);
    }

    private static String AT_DMOSETVAFC = "AT+DMOSETVAFC";

    public void setAfc(int afc, Callback callback) {
        String atCmd = AT_DMOSETVAFC + "=" + afc;
        sendATCmd(atCmd, callback);
    }

    private static String AT_DMOGETVAFC = "AT+DMOGETVAFC";

    public void getAfc(Callback callBack) {
        String atCmd = AT_DMOGETVAFC;
        sendATCmd(atCmd, callBack);
    }

    private static String AT_DMORDRSSI = "AT+DMORDRSSI";

    public void getRssi(Callback callBack) {
        String atCmd = AT_DMORDRSSI;
        sendATCmd(atCmd, callBack);
    }

    private static String AT_DMOCONNECT = "AT+DMOCONNECT";

    public void connect(Callback callback) {
        String atCmd = AT_DMOCONNECT;
        sendATCmd(atCmd, callback);
    }

    private static String AT_DMODISCONNECT = "AT+DMODISCONNECT";

    public void disconnect(Callback callback) {
        String atCmd = AT_DMODISCONNECT;
        sendATCmd(atCmd, callback);
    }

    public static final String AT_CHSWITCH = "AT+DMOCHSWITCH";

    public void setChSwitch(int ic, Callback callback) {
        String atCmd = AT_CHSWITCH + "=" + ic;
        sendATCmd(atCmd, callback);
    }

    public static final String AT_BINARY = "AT+BINARY";

    public void binary(String binary, Callback callback) {
        String atCmd = AT_BINARY + "=" + binary;
        sendATCmd(atCmd, callback);
    }

    public static final String AT_SETPWRSAVELV = "AT+DMOSETPWRSAVELV";

    public void setPwrsaveLv(String lv, Callback callback) {
        String atCmd = AT_SETPWRSAVELV + "=" + lv;
        sendATCmd(atCmd, callback);
    }

    public static final String AT_SETCHFREQ = "AT+DMOSETCHFREQ";

    public void setChfreq(String txf, String rxf, Callback callback) {
        String atCmd = AT_SETCHFREQ + "=<" + txf + ">,<" + rxf + ">";
        sendATCmd(atCmd, callback);
    }

    public void startCMD() {
        if (mReadThread == null) {
            mReadThread = new ReadThread();
            mReadThread.start();
        }
    }

    public void sendATCmd(String atCmd, Callback callback) {
        LogUtil.put(this, "send AT order = " + atCmd, LogUtil.WARN);
        if (logCall != null) {
            logCall.onLogPut("\r\n发出的指令 = " + atCmd);
        }
//        startCMD();
        this.callback = callback;
        int i;
        CharSequence t = atCmd + "\r";
        char[] text = new char[t.length()];
        for (i = 0; i < t.length(); i++) {
            text[i] = t.charAt(i);
        }
        try {
//            mSerialPort = mApplication.getSerialPort(DEVICE_PATH, DEVICE_BAUD_RATE);
//            mOutputStream = mSerialPort.getOutputStream();
            mOutputStream.write(new String(text).getBytes());
            mOutputStream.write('\n');
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        }

    }

    private static final int TIME_OUT = 10001;
    private static final int CONNECT_SUCCESS = 100;
    private static final int CONNECT_FAIL = 101;

    public void open() {
        if (mReadThread == null) {
            mReadThread = new ReadThread();
            mReadThread.start();
        }
        setTalkieStatus(TALKIE_STATE_PATH, TALKIE_STATE_ON);
//        sendATCmd(" ", null);
    }

    public void close() {
        setTalkieStatus(TALKIE_STATE_PATH, TALKIE_STATE_OFF);
    }

    public void interrupt() {
        if (mReadThread != null && mReadThread.isAlive()) {
            mReadThread.interrupt();
        }
    }

    private static final String TALKIE_STATE_PATH = "sys/devices/platform/talkie@0/talkieenablestatus";
    private static final String TALKIE_STATE_ON = "1";
    private static final String TALKIE_STATE_OFF = "0";

    private void setTalkieStatus(String path, String node) {
        try {
            BufferedWriter bufWriter = null;
            bufWriter = new BufferedWriter(new FileWriter(path));
            bufWriter.write(node);  // 写操作
            bufWriter.close();
            LogUtil.put(this, " write successful talkie = " + node + " by IO", LogUtil.WARN);
        } catch (IOException e) {
            e.printStackTrace();
            LogUtil.put(this, " can't write " + path + e.getMessage(), e);
        }
    }

    interface logCall {
        void onLogPut(String log);
    }

}
